package add.add;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;

public class Calculator extends JFrame {
    private final String[] FH = { "+", "-", "*",
                                  "/", ".", "=", "C",
                                 "sin", "cos", "tan",
                                "^", "log","sqrt","B"
    };
    CharSequence FHH[] = { "+", "-", "*", "÷" };
    private JPanel btjp = new JPanel();// 创建面板容器
    private JTextField jt = new JTextField();// 创建文本框

    public Calculator(String title) {
        super(title);
        btjp.setLayout(new GridLayout(6, 4, 20, 5));// 定义面板，并设置为网格布局，5行4列，组件水平距离为20，垂直距离为5
        JButton[] JBtn_1 = new JButton[10];
        JButton[] JBtn_2 = new JButton[FH.length];
        for (int i = 0; i <= 9; i++)
            JBtn_1[i] = new JButton(String.valueOf(i));// 数字按键
        for (int i = 0; i <= 9; i++) {
            JBtn_1[i].setFont(new Font("宋体", Font.BOLD, 30));// 给数字按键调整字体大小
        }
        for (int i = 0; i < FH.length; i++)
            JBtn_2[i] = new JButton(String.valueOf(FH[i]));// 符号按键
        for (int i = 0; i < FH.length; i++) {
            //System.out.println(FH[i]);
            JBtn_2[i].setFont(new Font("宋体", Font.BOLD, 30));// 给符号按键调整字体大小
        }
        // 把这些按钮按照事先排好的顺序，按在面板容器
        btjp.add(JBtn_1[1]);
        btjp.add(JBtn_1[2]);
        btjp.add(JBtn_1[3]);
        btjp.add(JBtn_2[0]);
        btjp.add(JBtn_1[4]);
        btjp.add(JBtn_1[5]);
        btjp.add(JBtn_1[6]);
        btjp.add(JBtn_2[1]);
        btjp.add(JBtn_1[7]);
        btjp.add(JBtn_1[8]);
        btjp.add(JBtn_1[9]);
        btjp.add(JBtn_2[2]);
        btjp.add(JBtn_2[4]);
        btjp.add(JBtn_1[0]);
        btjp.add(JBtn_2[6]);
        btjp.add(JBtn_2[3]);
        for (int i = 5; i < FH.length; i++)
            btjp.add(JBtn_2[i]);
		btjp.add(JBtn_2[5]);
		btjp.add(JBtn_2[6]);
		btjp.add(JBtn_2[7]);
		btjp.add(JBtn_2[8]);
        jt.setHorizontalAlignment(JTextField.RIGHT);// 文本框内容右侧对齐
        jt.setFont(new Font("宋体", Font.BOLD, 30));
        // JBtn_1[2].setFont(new Font("宋体",Font.BOLD,30));
        jt.setPreferredSize(new Dimension(200, 100));// 文本框为宽200，长100
        // 以下this是指主窗口JFrame
        this.add(jt, BorderLayout.NORTH);// 将文本框放在靠北的地方
        this.add(btjp, BorderLayout.CENTER);// 将面板容器放在中央
        this.setSize(700, 700);// 设置主窗口的大小
        this.setResizable(true);// 表示生成的窗体能够是否有用户改变大小，false表示不能，true代表能
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 使用 System exit 方法退出应用程序。
        this.setVisible(true);
        // etVisible(true)并不是告诉JVM让该控件可见，而是在内部调用repaint方法把各个控件画出来进行显示。
        // 如果在控件还没完全添加完其他控件就setVisible(true)那么在方法后面添加的控件都不能显示
        for (int i = 0; i <= 9; i++)
            JBtn_1[i].addActionListener(new number());// 为事件源增加监听器
        for (int i = 0; i < FH.length; i++)
            JBtn_2[i].addActionListener(new number());
    }

    private class number extends WindowAdapter implements ActionListener {// 重写监听器里面的内容
        public void actionPerformed(ActionEvent e) {// 这个是ActionListener这个接口里面的方法,监听器里的方法
            // TODO Auto-generated method stub
            // getActionCommand()依赖于按钮上的字符串
//			getSource得到的组件的名称，而getActionCommand得到的是标签。
//			如：Button bt=new Button("buttons");
//			用getSource得到的是bt 而用getActionCommand得到的是:buttons
            if (!e.getActionCommand().equals("=") && !e.getActionCommand().equals("C")&&!e.getActionCommand().equals("<-")) {
                jt.setText(jt.getText() + e.getActionCommand());// 在文本框中显示
            } //
            else if(e.getActionCommand().equals("<-")) {
                String Formula = jt.getText();
                int len = Formula.length();
                if(len!=0) {
                    String s = String.valueOf(Formula.substring(0,len-1));
                    jt.setText(s);
                }
            }
            else if (e.getActionCommand().equals("=")) {
                String Formula = jt.getText();
                if (Formula.contains(FHH[0])) {// java中contains方法是判断是否存在包含关系的，
                    // 1.java中String元素下标从0开始，substring(a)是从第a个字符开始截取，包含第a个字符。可以看成数学中的[ ），表示左闭右开区间
                    // 2.substring(a, b)表示截取下标从a开始到b结束的字符，包含第a个字符但是不包含第b个字符，可以看成[a,b)。
                    // Double.parseDouble方法是把数字类型的字符串，转换成double类型
                    // Double.valueOf方法是把数字类型的字符串，转换成Double类型
                    double number_1 = Double.parseDouble(Formula.substring(0, Formula.indexOf('+')));
                    double number_2 = Double.parseDouble(Formula.substring(Formula.indexOf('+') + 1));
                    jt.setText(String.valueOf(number_1 + number_2));
                }
                else if (Formula.contains(FHH[2])) {
                    double number_1 = Double.parseDouble(Formula.substring(0, Formula.indexOf('*')));
                    double number_2 = Double.parseDouble(Formula.substring(Formula.indexOf('*') + 1));
                    jt.setText(String.valueOf(number_1 * number_2));
                }
                else if (Formula.contains(FHH[3])) {
                    double number_1 = Double.parseDouble(Formula.substring(0, Formula.indexOf('/')));
                    double number_2 = Double.parseDouble(Formula.substring(Formula.indexOf('/') + 1));
                    try {
                        check(number_1, number_2);
                    } catch (YiChangException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }

                    jt.setText(String.valueOf(number_1 / number_2));
                }
                else if (Formula.contains("sin")) {
                    double number = Double.parseDouble(Formula.substring(Formula.indexOf('n') + 1));
                    double a = Math.toRadians(number);
                    jt.setText(String.valueOf(Math.sin(a)));
                }
                else if (Formula.contains("cos")) {
                    double number = Double.parseDouble(Formula.substring(Formula.indexOf('s') + 1));
                    double a = Math.toRadians(number);
                    jt.setText(String.valueOf(Math.cos(a)));
                }
                else if (Formula.contains("tan")) {
                    double number = Double.parseDouble(Formula.substring(Formula.indexOf('n') + 1));
                    double a = Math.toRadians(number);
                    jt.setText(String.valueOf(Math.tan(a)));
                }
                else if (Formula.contains("^")) {
                    double number_1 = Double.parseDouble(Formula.substring(0, Formula.indexOf('^')));
                    double number_2 = Double.parseDouble(Formula.substring(Formula.indexOf('^') + 1));
                    jt.setText(String.valueOf(Math.pow(number_1, number_2)));
                }
                else if (Formula.contains("log")) {
                    double number = Double.parseDouble(Formula.substring(Formula.indexOf('g') + 1));
                    jt.setText(String.valueOf(Math.log(number)));
                }
                else if (Formula.contains("sqrt")) {
                    double number = Double.parseDouble(Formula.substring(Formula.indexOf('t') + 1));
                    if(number<0)System.out.println("skadh");
                    try {
                        check2(number);
                    } catch (YiChangException2 e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                    jt.setText(String.valueOf(Math.sqrt(number)));
                }
                else if (Formula.contains(FHH[1])) {
                    double number_1 = Double.parseDouble(Formula.substring(0, Formula.indexOf('-')));
                    double number_2 = Double.parseDouble(Formula.substring(Formula.indexOf('-') + 1));
                    jt.setText(String.valueOf(number_1 - number_2));
                }
            } else {
                jt.setText(null);
            }
        }
    }

    void check(double x, double y) throws YiChangException {
        if (y == 0) {
            throw new YiChangException("您输入的分母为0，不能进行除法运算");
        } else
            return;
    }
    void check2(double x) throws YiChangException2 {
        if (x<0) {
            throw new YiChangException2("您输入的数为负数，不能进行开方运算");
        } else
            return;
    }

    public static void main(String[] args) {
        new Calculator("计算器");
    }
}
class YiChangException2 extends Exception {
    public YiChangException2() {
    }

    public YiChangException2(String message) {
        super(message);
    }
}
class YiChangException extends Exception {
    public YiChangException() {
    }

    public YiChangException(String message) {
        super(message);
    }
}